package com.unswift.utils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.HashSet;
import java.util.Set;

import com.unswift.annotation.api.Api;
import com.unswift.annotation.api.ApiField;
import com.unswift.annotation.api.ApiMethod;

@Api(value="数字公共操作类", author="unswift", date="2022-12-16", version="1.0.0")
public final class NumberUtils {
	
	@ApiField("数字反射类Set集合")
	private final static Set<String> NUMBER_CLASS_SET=new HashSet<String>();
	
	static{
		NUMBER_CLASS_SET.add("java.lang.Boolean");
		NUMBER_CLASS_SET.add("java.lang.Byte");
		NUMBER_CLASS_SET.add("java.lang.Short");
		NUMBER_CLASS_SET.add("java.lang.Integer");
		NUMBER_CLASS_SET.add("java.lang.Long");
		NUMBER_CLASS_SET.add("java.lang.Float");
		NUMBER_CLASS_SET.add("java.lang.Double");
		NUMBER_CLASS_SET.add("java.math.BigDecimal");
	}
	
	@ApiField("数字格式化本地线程变量")
	public static ThreadLocal<DecimalFormat> formatLocal=new InheritableThreadLocal<DecimalFormat>(){
		protected DecimalFormat initialValue() {//初始化本线程变量
			return new DecimalFormat();
		};
	};

	@ApiMethod(value="将对象转换未BigDecimal类型，如果出现例外，则返回特殊情况", params={@ApiField("需要转换的对象"), @ApiField("例外"), @ApiField("例外返回")}, returns=@ApiField("转换后的对象"))
	public static BigDecimal toDecimal(Object source, String exception, String exceptionBack){
		if(ObjectUtils.isEmpty(source)){
			return null;
		}
		if(ObjectUtils.isNotEmpty(exception)){
			if(exception.equals(source)){
				if(ObjectUtils.isEmpty(exceptionBack)){
					return null;
				}else{
					return new BigDecimal(exceptionBack);
				}
			}
		}
		return new BigDecimal(source.toString());
	}
	
	/**
	 * 求百分比
	 * @param molecule 分子
	 * @param denominator 分母
	 * @param scale 精度
	 * @return
	 */
	@ApiMethod(value="根据分子，分母求百分比", params={@ApiField("分子"), @ApiField("分母"), @ApiField("精度")}, returns=@ApiField("百分比BigDecimal对象"))
	public static BigDecimal findPercentage(Number molecule, Number denominator, int scale){
		if(ObjectUtils.isEmpty(molecule) || ObjectUtils.isEmpty(denominator) || denominator.doubleValue()==0){
			return new BigDecimal(0);
		}
		return new BigDecimal(molecule.doubleValue()*100.0/denominator.doubleValue()).setScale(scale, RoundingMode.HALF_UP);
	}
	
	@ApiMethod(value="将数字按照指定格式格式化", params={@ApiField("数字"), @ApiField("格式，如：#.##、#,###.##等")})
	public static String format(Number number, String format){
		DecimalFormat decimalFormat = formatLocal.get();
		decimalFormat.applyPattern(format);
		return decimalFormat.format(number);
	}
	
	@ApiMethod(value="判断类路径是否为数字", params=@ApiField("类路径"), returns=@ApiField("是否为数字类型，true：是，false：不是"))
	public static boolean typeIsNumber(String className){
		return NUMBER_CLASS_SET.contains(className);
	}
	
	@ApiMethod(value="判断一个对象是否为数字", params={@ApiField("判断的对象"), @ApiField("如果为null，则返回指定值")}, returns=@ApiField("是否为数字，true：是，false：不是"))
	public static boolean isNumber(Object source, boolean nullTrue){
		if(ObjectUtils.isEmpty(source)){
			return nullTrue;
		}
		return source.toString().matches("^[\\-]?[0-9]+$");
	}
	
	@ApiMethod(value="判断一个对象是否为数字", params={@ApiField("判断的对象"), @ApiField("如果为null，则返回指定值")}, returns=@ApiField("是否为数字，true：是，false：不是"))
	public static boolean isUnsignedNumber(Object source, boolean nullTrue){
		if(ObjectUtils.isEmpty(source)){
			return nullTrue;
		}
		return source.toString().matches("^[0-9]+$");
	}
	
	@ApiMethod(value="判断一个对象是否包含数字", params={@ApiField("判断的对象"), @ApiField("如果为null，则返回指定值")}, returns=@ApiField("是否包含数字，true：包含，false：不"))
	public static boolean containsNumber(String source, boolean nullTrue){
		if(ObjectUtils.isEmpty(source)){
			return nullTrue;
		}
		int length=source.length();
		for (int i = 0; i < length; i++) {
			if(isNumber(source.charAt(i)+"", nullTrue)){
				return true;
			}
		}
		return false;
	}
	
	@ApiMethod(value="判断一个对象是否是一个小数", params={@ApiField("判断的对象"), @ApiField("如果为null，则返回指定值")}, returns=@ApiField("是否为数字，true：是，false：不是"))
	public static boolean isDecimal(Object source, boolean nullTrue){
		if(ObjectUtils.isEmpty(source)){
			return nullTrue;
		}
		return source.toString().matches("^[\\-]?[0-9.]+$");
	}
	
	@ApiMethod(value="将计算机bit单位转换为可阅读的单位，转换规则：1G=1024M...", params=@ApiField("big的大小"), returns=@ApiField("可阅读的大小"))
	public static String showCapacity(long capacity){
		if(capacity<1024){
			return capacity+"B";
		}else if(capacity<1024L*1024){
			return NumberUtils.format(new BigDecimal(capacity/1024.0).setScale(3, RoundingMode.HALF_UP), "#")+"KB";
		}else if(capacity<1024L*1024*1024){
			return NumberUtils.format(new BigDecimal(capacity/1024.0/1024).setScale(3, RoundingMode.HALF_UP), "#")+"MB";
		}else{
			return NumberUtils.format(new BigDecimal(capacity/1024.0/1024/1024).setScale(3, RoundingMode.HALF_UP), "#")+"GB";
		}
	}
	
	@ApiMethod(value="两个对象相除", params={@ApiField("分子"), @ApiField("分母"), @ApiField("精度"), @ApiField("精度模式")}, returns=@ApiField("相除结果"))
	public static BigDecimal divide(Object beDivisor, Object divisor, int scale, RoundingMode roundingMode){
		return new BigDecimal(beDivisor.toString()).divide(new BigDecimal(divisor.toString()), scale, roundingMode);
	}
	
	@ApiMethod(value="两个对象相乘", params={@ApiField("被乘数"), @ApiField("乘数"), @ApiField("精度"), @ApiField("精度模式")}, returns=@ApiField("相乘结果"))
	public static BigDecimal multiply(Object multiplicand, Object multiplier, int scale, RoundingMode roundingMode){
		BigDecimal multiply = new BigDecimal(multiplicand.toString()).multiply(new BigDecimal(multiplier.toString()));
		multiply.setScale(scale, roundingMode);
		return multiply;
		
	}
	
	@ApiMethod(value="两个对象相减", params={@ApiField("被减数"), @ApiField("减数")}, returns=@ApiField("相减结果"))
	public static BigDecimal sub(Object sub2, Object sub1){
		BigDecimal multiply = new BigDecimal(sub2.toString()).subtract(new BigDecimal(sub1.toString()));
		return multiply;
		
	}
	
	@ApiMethod(value="两个对象相加", params={@ApiField("被加数"), @ApiField("加数")}, returns=@ApiField("相加结果"))
	public static BigDecimal add(Object add2, Object add1){
		BigDecimal multiply = new BigDecimal(add2.toString()).add(new BigDecimal(add1.toString()));
		return multiply;
		
	}
}
